////////////////////////////////////////////////////////////////////
// Last svn revision: $Id:  $ 
////////////////////////////////////////////////////////////////////

#include <iostream>
#include <stdio.h>
#include <sstream>
#include <float.h>
#include "MLCTest/ATestClass.hh"


using namespace drow;
using namespace test;

std::map<std::string, ATestClass*> ATestClass::fClasses;

ATestClass::ATestClass(const std::string& name)
{
	fClasses[name] = this;
}

void ATestClass::Test()
{
	CreateTestClasses();
	TestAllClasses();
}

void ATestClass::TestAllClasses()
{
	std::cout << "Start running all tests." << std::endl;

	std::map<std::string, ATestClass*>::iterator iter;
	for( iter = fClasses.begin(); iter != fClasses.end(); iter++ ) {
		std::cout << "Testing class " << iter->first << "... " << std::flush;
		bool passed = true;
		try {
            iter->second->TestClass();
		}
		catch(int message) {
            std::cout << "Assert failed: line " << message << "; ";
            passed = false;
		}
		catch(...) {
            std::cout << "Unknown exception occured; ";
            passed = false;
		}
		if(passed) {
            std::cout << "Passed" << std::endl;
		}
		else {
            std::cout << "Failed" << std::endl;
		}
	}	

	std::cout << "Finished running all tests sucessfully." << std::endl;
}

void ATestClass::AssertTrue(const bool b, const int line) {
    if(b == false) throw line;
}

void ATestClass::AssertEquality(const double d0, const double d1, const int line) {
    double dif = d1 - d0;
    dif = dif < 0 ? -dif : dif;
    AssertTrue(dif < DBL_EPSILON, line);
}

void ATestClass::AssertFailure(const std::function<void()> func, const int line) {
    bool funcException = false;
    try {
        func();
    }
    catch(...) {
        funcException = true;
    }
    if (!funcException) AssertTrue(false, line);
}

// all includes for test classes go here
#include "MLCTest/TDefaultComplexOp.hh"
#include "MLCTest/TDefaultMatrixOp.hh"
#include "MLCTest/TComplexOp.hh"

void ATestClass::CreateTestClasses()
{
	// All new test classes go here
    new TDefaultComplexOp();
    new TDefaultMatrixOp();
    new TComplexOp();
}